#ifdef HIGHPRECISION
precision highp float;
#else
precision mediump float;
#endif

#include?DIRECTIONLIGHT||POINTLIGHT||SPOTLIGHT "LightHelper.glsl";

uniform vec4 u_Albedo;

#ifdef ALPHATEST
uniform float u_AlphaTestValue;
#endif

#ifdef DIFFUSEMAP
uniform sampler2D u_DiffuseTexture;
#endif

#ifdef REFLECTMAP
uniform samplerCube u_ReflectTexture;
uniform vec3 u_MaterialReflect;
#endif

#if   defined(DIFFUSEMAP)||((defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&(defined(COLOR)&&defined(SPECULARMAP)||defined(NORMALMAP)))
varying vec2 v_Texcoord0;
#endif

#ifdef defined(AMBIENTMAP)||defined(LIGHTMAP)
varying vec2 v_LightMapUV;
#endif
#ifdef AMBIENTMAP
uniform sampler2D u_AmbientTexture;
#endif
#ifdef LIGHTMAP
uniform sampler2D u_LightMap;
#endif

#ifdef COLOR
varying vec4 v_Color;
#endif

#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)
uniform vec3 u_MaterialDiffuse;
uniform vec4 u_MaterialSpecular;
  #if (defined(DIFFUSEMAP)||defined(COLOR))&&defined(SPECULARMAP) 
  uniform sampler2D u_SpecularTexture;
  #endif
#endif

#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(AMBIENTMAP)||defined(LIGHTMAP)
uniform vec3 u_MaterialAmbient;
#endif

#if defined(FOG)||defined(DEPTHFOG)
	uniform float u_FogStart;
	uniform float u_FogRange;
	#if ADDTIVEFOG
	#else
		uniform vec3 u_FogColor;
	#endif
#endif


#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(REFLECTMAP)
varying vec3 v_Normal;
#endif

#if (defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&defined(NORMALMAP)
uniform sampler2D u_NormalTexture;
varying vec3 v_Tangent0;
#endif

#ifdef DIRECTIONLIGHT
uniform DirectionLight u_DirectionLight;
#endif

#ifdef POINTLIGHT
uniform PointLight u_PointLight;
#endif

#ifdef SPOTLIGHT
uniform SpotLight u_SpotLight;
#endif

uniform vec3 u_AmbientColor;


#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(FOG)||defined(DEPTHFOG)||defined(REFLECTMAP)||(defined(RECEIVESHADOW)&&(defined(SHADOWMAP_PSM2)||defined(SHADOWMAP_PSM3)))
uniform vec3 u_CameraPos;
#endif
#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(FOG)||defined(DEPTHFOG)||defined(REFLECTMAP)
varying vec3 v_PositionWorld;
#endif

#include "ShadowHelper.glsl"
#ifdef RECEIVESHADOW
	#if defined(SHADOWMAP_PSSM2)||defined(SHADOWMAP_PSSM3)
	uniform mat4 u_lightShadowVP[4];
	#endif
	#ifdef SHADOWMAP_PSSM1 
	varying vec4 v_lightMVPPos;
	#endif
#endif
varying float v_posViewZ;



void main_castShadow()
{
	//gl_FragColor=vec4(v_posViewZ,0.0,0.0,1.0);
	gl_FragColor=packDepth(v_posViewZ);
	#if defined(DIFFUSEMAP)&&defined(ALPHATEST)
		float alpha = texture2D(u_DiffuseTexture,v_Texcoord0).w;
		if( alpha < u_AlphaTestValue )
		{
			discard;
		}
	#endif
}
void main_normal()
{
#if defined(DIFFUSEMAP)&&!defined(COLOR)
	gl_FragColor=texture2D(u_DiffuseTexture, v_Texcoord0);
#endif 
  
#if defined(COLOR)&&!defined(DIFFUSEMAP)
	gl_FragColor=v_Color;
#endif 
  
#if defined(DIFFUSEMAP)&&defined(COLOR)
	vec4 texColor=texture2D(u_DiffuseTexture, v_Texcoord0);
	gl_FragColor=texColor*v_Color;
#endif
  
#if !defined(DIFFUSEMAP)&&!defined(COLOR)
	gl_FragColor=vec4(1.0,1.0,1.0,1.0);
#endif 
    
#ifdef ALPHATEST
	if(gl_FragColor.a-u_AlphaTestValue<0.0)
		discard;
#endif
  
  
#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(REFLECTMAP)
	vec3 normal;
    #if (defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&defined(NORMALMAP)
		vec3 normalMapSample = texture2D(u_NormalTexture, v_Texcoord0).rgb;
		normal = normalize(NormalSampleToWorldSpace(normalMapSample, v_Normal, v_Tangent0));
	#else
		normal = normalize(v_Normal);
    #endif
#endif
	
#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)
	vec3 diffuse = vec3(0.0);
	vec3 ambient = vec3(0.0);
	vec3 specular= vec3(0.0);
	vec3 dif, amb, spe;
#endif
  
#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(FOG)||defined(REFLECTMAP)
	vec3 toEye;
	#ifdef FOG
		toEye=u_CameraPos-v_PositionWorld;
		float toEyeLength=length(toEye);
		toEye/=toEyeLength;
	#else
		toEye=normalize(u_CameraPos-v_PositionWorld);
	#endif
#endif
	
#ifdef DIRECTIONLIGHT
	computeDirectionLight(u_MaterialDiffuse,u_MaterialAmbient,u_MaterialSpecular,u_DirectionLight,u_AmbientColor,normal,toEye, dif, amb, spe);
	diffuse+=dif;
	ambient+=amb;
	specular+=spe;
#endif
 
#ifdef POINTLIGHT
	computePointLight(u_MaterialDiffuse,u_MaterialAmbient,u_MaterialSpecular,u_PointLight,u_AmbientColor,v_PositionWorld,normal,toEye, dif, amb, spe);
	diffuse+=dif;
	ambient+=amb;
	specular+=spe;
#endif

#ifdef SPOTLIGHT
	ComputeSpotLight(u_MaterialDiffuse,u_MaterialAmbient,u_MaterialSpecular,u_SpotLight,u_AmbientColor,v_PositionWorld,normal,toEye, dif, amb, spe);
	diffuse+=dif;
	ambient+=amb;
	specular+=spe;
#endif

#ifdef RECEIVESHADOW
	float shadowValue = 1.0;
	#ifdef SHADOWMAP_PSSM3
		shadowValue = getShadowPSSM3( u_shadowMap1,u_shadowMap2,u_shadowMap3,u_lightShadowVP,u_shadowPSSMDistance,u_shadowPCFoffset,v_PositionWorld,v_posViewZ,0.001);
	#endif
	#ifdef SHADOWMAP_PSSM2
		shadowValue = getShadowPSSM2( u_shadowMap1,u_shadowMap2,u_lightShadowVP,u_shadowPSSMDistance,u_shadowPCFoffset,v_PositionWorld,v_posViewZ,0.001);
	#endif 
	#ifdef SHADOWMAP_PSSM1
		shadowValue = getShadowPSSM1( u_shadowMap1,v_lightMVPPos,u_shadowPSSMDistance,u_shadowPCFoffset,v_posViewZ,0.001);
	#endif
#endif

#ifdef AMBIENTMAP
	#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)
		gl_FragColor.rgb=gl_FragColor.rgb*(u_MaterialAmbient+texture2D(u_AmbientTexture, v_LightMapUV).rgb); 
	#else
		#if defined(RECEIVESHADOW)
			gl_FragColor.rgb=gl_FragColor.rgb*(u_MaterialAmbient+texture2D(u_AmbientTexture, v_LightMapUV).rgb * shadowValue);
		#else
			gl_FragColor.rgb=gl_FragColor.rgb*(u_MaterialAmbient+texture2D(u_AmbientTexture, v_LightMapUV).rgb); 
		#endif
	#endif
#endif

#ifdef LIGHTMAP
	#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)
		gl_FragColor.rgb=gl_FragColor.rgb*(u_MaterialAmbient+texture2D(u_LightMap, v_LightMapUV).rgb); 
	#else
		#if defined(RECEIVESHADOW)
			gl_FragColor.rgb=gl_FragColor.rgb*(u_MaterialAmbient+texture2D(u_LightMap, v_LightMapUV).rgb * shadowValue);
		#else
			gl_FragColor.rgb=gl_FragColor.rgb*(u_MaterialAmbient+texture2D(u_LightMap, v_LightMapUV).rgb); 
		#endif
	#endif
#endif

gl_FragColor=gl_FragColor*u_Albedo;

#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)
	#if (defined(DIFFUSEMAP)||defined(COLOR))&&defined(SPECULARMAP)
		specular =specular*texture2D(u_SpecularTexture, v_Texcoord0).rgb;
    #endif
	#ifdef RECEIVESHADOW
		gl_FragColor =vec4( gl_FragColor.rgb*(ambient + diffuse*shadowValue) + specular*shadowValue,gl_FragColor.a);
	#else
		gl_FragColor =vec4( gl_FragColor.rgb*(ambient + diffuse) + specular,gl_FragColor.a);
	#endif
#endif
  
#ifdef REFLECTMAP
	vec3 incident = -toEye;
	vec3 reflectionVector = reflect(incident,normal);
	vec3 reflectionColor  = textureCube(u_ReflectTexture,reflectionVector).rgb;
	gl_FragColor.rgb += u_MaterialReflect*reflectionColor;
#endif
  
#ifdef FOG
	float lerpFact=clamp((toEyeLength-u_FogStart)/u_FogRange,0.0,1.0);
	#if ADDTIVEFOG
		gl_FragColor.rgb=mix(gl_FragColor.rgb,vec3(0.0,0.0,0.0),lerpFact);
	#else
		gl_FragColor.rgb=mix(gl_FragColor.rgb,u_FogColor,lerpFact);
	#endif
#endif
#ifdef DEPTHFOG
	float lerpFact = (-v_PositionWorld.y-u_FogStart)/u_FogRange;
	gl_FragColor.rgb=mix(gl_FragColor.rgb,u_FogColor,lerpFact);
#endif
}

void main()
{
#ifdef CASTSHADOW		
	main_castShadow();
#else
  main_normal();
#endif  
}

